package cc.rengu.igas.channel.nucc.core.realize.impl;

import cc.rengu.igas.channel.nucc.core.realize.NuccEncSignService;
import cc.rengu.oltp.service.common.entity.CertInfo;
import cc.rengu.oltp.utility.util.AESUtil;
import cc.rengu.oltp.utility.util.RSAUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import org.apache.commons.codec.binary.Base64;

import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.List;

/**
 * 签名服务实现
 */
public class NuccEncSignServiceImpl implements NuccEncSignService {
    private static final String algorAES = "AES";
    private static final String algorRSA2 = "SHA256WithRSA";
    private static final String charset = "UTF-8";
    private RgLogger rgLog = RgLog.getLogger(this.getClass().getName());

    @Override
    public String generateSignString(CertInfo certInfo, String signData) throws Exception {
        if ("0".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            RSAPrivateKey privateKey = RSAUtil.getPrivateKeyFromBase64String(certInfo.getCertValue());
            if (certInfo.getAlgorithmType().contains("RSA")) {
                return RSAUtil.generateSignString(signData, privateKey, (null == certInfo.getAlgorithmType()) ? algorRSA2 : certInfo.getAlgorithmType(), charset);
            } else {
                rgLog.debug("暂不支持签名算法CertSaveType:<{}>,", certInfo.getCertSaveType());
                return null;
            }
        } else if ("1".equals(certInfo.getCertSaveType())) {
            //调用加密机需自己客户化
            return null;
        } else if ("2".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            List<String> aliasList = RSAUtil.getCertAliasFromPfxCertFile(certInfo.getCertSavePath(), certInfo.getCertPassword());
            RSAPrivateKey privateKey = RSAUtil.getPrivateKeyFromCertFile(certInfo.getCertSavePath(), aliasList.get(0), certInfo.getCertPassword());
            return RSAUtil.generateSignString(signData, privateKey, certInfo.getAlgorithmType(), charset);
        } else {
            rgLog.debug("不支持密钥存储类型CertSaveType:<{}>,", certInfo.getCertSaveType());
            return null;
        }
    }

    @Override
    public boolean verifySignString(CertInfo certInfo, String sign, String signBlock) throws Exception {
        // 判断证书/密钥类型,通过软加密还是硬加密方式（0-本地数据库存储,1-加密机,2-本地文件）
        if ("0".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            RSAPublicKey publicKey = RSAUtil.getPublicKeyFromBase64String(certInfo.getCertValue());
            return RSAUtil.verifySignString(signBlock, sign, publicKey, (null == certInfo.getAlgorithmType()) ? algorRSA2 : certInfo.getAlgorithmType(), charset);
        } else if ("1".equals(certInfo.getCertSaveType())) {
            //需要自己客户化
            return false;
        } else if ("2".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            RSAPublicKey publicKey = RSAUtil.getPublicKeyFromCertFile(certInfo.getCertSavePath());
            return RSAUtil.verifySignString(signBlock, sign, publicKey, certInfo.getAlgorithmType(), charset);
        }
        return false;
    }

    @Override
    public String encryptedInfo(CertInfo certInfo, String data) throws Exception {
        if ("0".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            if (certInfo.getAlgorithmType().contains(algorAES)) {
                return AESUtil.pkcs5EcbEncryptData(certInfo.getCertValue(), data);
            } else if (certInfo.getAlgorithmType().contains("RSA")) {
                RSAPublicKey publicKey = RSAUtil.getPublicKeyFromBase64String(certInfo.getCertValue());
                return RSAUtil.publicKeyEncrypt(data, publicKey);
            } else {
                rgLog.debug("暂不支持软加密的算法类型:<{}>,", certInfo.getAlgorithmType());
            }
        } else if ("1".equals(certInfo.getCertSaveType())) {
            //调用加密机需自己客户化
            return null;
        } else {
            rgLog.debug("不支持密钥存储类型CertSaveType:<{}>,", certInfo.getCertSaveType());
            return null;
        }
        return null;
    }

    @Override
    public String descryptedInfo(CertInfo certInfo, String encData) throws Exception {
        if ("0".equals(certInfo.getCertSaveType())) {
            rgLog.debug("使用软加密,算法类型:<{}>,", certInfo.getAlgorithmType());
            if (certInfo.getAlgorithmType().contains(algorAES)) {
                return AESUtil.pkcs5EcbDecryptData(certInfo.getCertValue(), encData);
            } else if (certInfo.getAlgorithmType().contains("RSA")) {
                RSAPrivateKey privateKey = RSAUtil.getPrivateKeyFromBase64String(certInfo.getCertValue());
                return RSAUtil.privateKeyDecrypt(Base64.decodeBase64(encData), privateKey);
            } else {
                rgLog.debug("暂不支持软加密的算法类型:<{}>,", certInfo.getAlgorithmType());
            }
        } else if ("1".equals(certInfo.getCertSaveType())) {
            //调用加密机需自己客户化
            return null;
        } else {
            rgLog.debug("不支持密钥存储类型CertSaveType:<{}>,", certInfo.getCertSaveType());
            return null;
        }
        return null;
    }

}
